package com.lzw.bluetoothpractice.Activitys;

import androidx.annotation.RequiresApi;
import androidx.appcompat.widget.ViewUtils;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

import android.Manifest;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lzw.bluetoothpractice.Adapters.BLEAdapters;
import com.lzw.bluetoothpractice.Adapters.RecommendDoctorListAdapter;
import com.lzw.bluetoothpractice.AppConfig;
import com.lzw.bluetoothpractice.Models.Device;
import com.lzw.bluetoothpractice.MyApplication;
import com.lzw.bluetoothpractice.R;
import com.lzw.bluetoothpractice.Utils.AppUtil;
import com.lzw.bluetoothpractice.Utils.BleAdvertisedData;
import com.lzw.bluetoothpractice.Utils.BleUtil;
import com.lzw.bluetoothpractice.Utils.SharePreferenceUtils;
import com.lzw.bluetoothpractice.Utils.Utils;
import com.lzw.bluetoothpractice.bean.RecommendDoctorBean;
import com.lzw.bluetoothpractice.network.HeadAssmblyUtils;
import com.lzw.bluetoothpractice.network.RetrofitManager;
import com.lzw.bluetoothpractice.network.api.RequestApi;
import com.tbruyelle.rxpermissions2.RxPermissions;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import static android.bluetooth.BluetoothDevice.TRANSPORT_LE;
import static com.lzw.bluetoothpractice.MyApplication.getContext;

public class SearchDeviceActivity extends BaseActivity {
    private static final String TAG ="ble_tag" ;
    private List<BluetoothDevice> mDatas=new ArrayList<>();;
    private boolean isScaning=false;
    TextView tvBindStatus;
    ImageView ivSerBleStatus;
    RelativeLayout rlSearch;
    RecyclerView recyclerView;
    BLEAdapters bleAdapters;
    private List<Integer> mRssis=new ArrayList<>();


    private BLEAdapters mAdapter;
    private BluetoothLeScanner mbleScanner;
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothManager mBluetoothManager;
    private BluetoothGatt mBluetoothGatt;
    private boolean isConnecting=false;
    private ArrayList<BluetoothDevice> selectDeviceMacs;

    private MyApplication application = (MyApplication)this.getApplication();
    private BluetoothDevice bluetoothDevice;
    private Map<String, String> keyMap;
    private UUID write_UUID_service;
    private UUID write_UUID_chara;
    private UUID read_UUID_service;
    private UUID read_UUID_chara;
    private UUID notify_UUID_service;
    private UUID notify_UUID_chara;
    private UUID indicate_UUID_service;
    private UUID indicate_UUID_chara;
    private String hex="7B46363941373237323532443741397D";
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search_device);
        initView();
        initData();
        mBluetoothManager=(BluetoothManager)getSystemService(BLUETOOTH_SERVICE);
        mBluetoothAdapter=mBluetoothManager.getAdapter();
        mbleScanner=mBluetoothAdapter.getBluetoothLeScanner();

        if(mBluetoothAdapter==null||!mBluetoothAdapter.isEnabled()){

            Intent intent=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);

            startActivityForResult(intent,0);
        }

    }
    private void initData(){

        selectDeviceMacs=new ArrayList<>();
        mAdapter=new BLEAdapters(mDatas,mRssis,SearchDeviceActivity.this,recyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));
        recyclerView.setAdapter(mAdapter);
        mAdapter.setOnItemClickListener(new BLEAdapters.OnRecyclerItemClickListener() {
            @Override
            public void onClick(View view, int position) {

            if (isScaning){
                stopSearchBlueTooth();
            }

            if (!isConnecting){

                BluetoothDevice bluetoothDevice= mDatas.get(position);
                if(selectDeviceMacs.contains(bluetoothDevice)){
                    Toast toast=Toast.makeText(SearchDeviceActivity.this,"设备已连接",Toast.LENGTH_SHORT);
                    toast.show();
                }else {
                    isConnecting=true;
                    selectDeviceMacs.add(bluetoothDevice);
                    tvBindStatus.setText("连接中");
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                        mBluetoothGatt = bluetoothDevice.connectGatt(SearchDeviceActivity.this,
                                true, gattCallback, TRANSPORT_LE);
                    } else {
                        mBluetoothGatt = bluetoothDevice.connectGatt(SearchDeviceActivity.this,
                                true, gattCallback);
                    }
                }
                //连接设备

            }
            }
        });

    }
    private void initView(){
        tvBindStatus=fd(R.id.tv_ser_bind_status);
        rlSearch=fd(R.id.layout_ser_ble);
        recyclerView=fd(R.id.rcList);
        ivSerBleStatus=findViewById(R.id.iv_ser_ble_status);

        ivSerBleStatus.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!isScaning){
                    checkPermissions();
                }else{
                    tvBindStatus.setText("停止搜索");
                    stopSearchBlueTooth();
                }

            }
        });

    }
    private void searchBlueTooth(){
        tvBindStatus.setText("正在搜索");
        isScaning=true;
        mBluetoothAdapter.startLeScan(leScanCallback);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                isScaning=false;
                stopSearchBlueTooth();
                tvBindStatus.setText("搜索结束");
            }
        },10000);



    }
    private  void stopSearchBlueTooth(){
        mBluetoothAdapter.stopLeScan(leScanCallback);
    }

    private BluetoothGattCallback gattCallback=new BluetoothGattCallback() {
        /**
         * 断开或连接 状态发生变化时调用
         * */
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            super.onConnectionStateChange(gatt, status, newState);
            Log.e(TAG,"onConnectionStateChange()");
            if (status==BluetoothGatt.GATT_SUCCESS){
                //连接成功
                if (newState== BluetoothGatt.STATE_CONNECTED){
                    Log.e(TAG,"连接成功");
                    //发现服务
                    gatt.discoverServices();
                }
            }else{
                //连接失败
                Log.e(TAG,"失败=="+status);
                mBluetoothGatt.close();
                isConnecting=false;
            }
        }
        /**
         * 发现设备（真正建立连接）
         * */
        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            super.onServicesDiscovered(gatt, status);
            //直到这里才是真正建立了可通信的连接
            isConnecting=false;
            Log.e(TAG,"onServicesDiscovered()---建立连接");

            Device device=new Device();
            device.setDeviceName(gatt.getDevice().getName());
            device.setDeviceMac(gatt.getDevice().getAddress());
            device.setUserId(Long.parseLong(SharePreferenceUtils.getString(getContext(),"userId",null)));


            try {
                keyMap = HeadAssmblyUtils.HeadAssembly("/dev-api/android/user/recommendDoctor");
            } catch (Exception e) {
                e.printStackTrace();
            }
            String accessToken = SharePreferenceUtils.getString(getContext(),"access_token",null);;

            RetrofitManager.getInstance(AppConfig.BASE_URL)
                    .createReq(RequestApi.class).addDevice(device,"*:*:*","1", AppUtil.getVersionCode() + "", accessToken ,keyMap.get("gmtStr"), keyMap.get("contentMD5"), keyMap.get("hmacCode")).
                    observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(new Subscriber<JSONObject>() {
                @Override
                public void onCompleted() {

                }

                @Override
                public void onError(Throwable e) {

                    Log.e("错误",e.getMessage()+"");

                }

                @Override
                public void onNext(JSONObject json) {

                    int code=(int)json.getInteger("code");
                    if(code==200){

                        Toast toast=Toast.makeText(SearchDeviceActivity.this,"添加设备信息成功",Toast.LENGTH_LONG);
                        toast.show();

                    }else {
                        Toast toast=Toast.makeText(SearchDeviceActivity.this,json.get("msg").toString(),Toast.LENGTH_LONG);
                        toast.show();
                    }

                }
            });
            //获取初始化服务和特征值
            initServiceAndChara();
            //订阅通知
            mBluetoothGatt.setCharacteristicNotification(mBluetoothGatt
                    .getService(notify_UUID_service).getCharacteristic(notify_UUID_chara),true);


            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                  //  bleListView.setVisibility(View.GONE);
                   // operaView.setVisibility(View.VISIBLE);
                    tvBindStatus.setText("已连接");
                }
            });
        }
        /**
         * 读操作的回调
         * */
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicRead(gatt, characteristic, status);
            Log.e(TAG,"onCharacteristicRead()");
        }
        /**
         * 写操作的回调
         * */
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            super.onCharacteristicWrite(gatt, characteristic, status);

            Log.e(TAG,"onCharacteristicWrite()  status="+status+",value="+Utils.bytesToString(characteristic.getValue()));
        }
        /**
         * 接收到硬件返回的数据
         * */
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            super.onCharacteristicChanged(gatt, characteristic);

            final byte[] data=characteristic.getValue();


            String dataStr=Utils.bytesToString(data);



            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(dataStr!=null){
                        String[] dataStr2=dataStr.split(",");
                        for (String s:
                                dataStr2) {
                            String [] dataStr3=s.split(":");
                            if (dataStr3[0].toString().equals("T")){

                                MyApplication.getInstance().temperature=dataStr3[1].trim().toString();
                                Log.e(TAG,"温度："+Double.parseDouble(dataStr3[1].toString()));
                            }else if(dataStr3[0].toString().equals("A")) {
                                Double angle=Double.parseDouble(dataStr3[1].trim().toString());
                                DecimalFormat df =  new  DecimalFormat(  "0.00" );
                                if(angle>180){
                                    angle=angle-180.0;
                                }
                                if(angle>135){
                                    angle=angle-90.0;
                                }
                                MyApplication.getInstance().angle=df.format(angle);
                                Log.e(TAG,"角度："+angle);
                            }else if(dataStr3[0].toString().equals("Step") ){
                                MyApplication.getInstance().step=dataStr3[1].trim();
                                Log.e(TAG,"步数："+dataStr3[1].toString());
                            }

                        }
                    }
                }
            });

        }
    };
    private static final String HEX = "0123456789abcdef";
    public static String bytes2hex(byte[] bytes)
    {
        StringBuilder sb = new StringBuilder(bytes.length * 2);
        for (byte b : bytes)
        {
            // 取出这个字节的高4位，然后与0x0f与运算，得到一个0-15之间的数据，通过HEX.charAt(0-15)即为16进制数
            sb.append(HEX.charAt((b >> 4) & 0x0f));
            // 取出这个字节的低位，与0x0f与运算，得到一个0-15之间的数据，通过HEX.charAt(0-15)即为16进制数
            sb.append(HEX.charAt(b & 0x0f));
        }
        return sb.toString();
    }
    private void initServiceAndChara(){
        List<BluetoothGattService> bluetoothGattServices= mBluetoothGatt.getServices();
        for (BluetoothGattService bluetoothGattService:bluetoothGattServices){
            List<BluetoothGattCharacteristic> characteristics=bluetoothGattService.getCharacteristics();
            for (BluetoothGattCharacteristic characteristic:characteristics){
                int charaProp = characteristic.getProperties();
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                    read_UUID_chara=characteristic.getUuid();
                    read_UUID_service=bluetoothGattService.getUuid();
                    Log.e(TAG,"read_chara="+read_UUID_chara+"----read_service="+read_UUID_service);
                }
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                    write_UUID_chara=characteristic.getUuid();
                    write_UUID_service=bluetoothGattService.getUuid();
                    Log.e(TAG,"write_chara="+write_UUID_chara+"----write_service="+write_UUID_service);
                }
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0) {
                    write_UUID_chara=characteristic.getUuid();
                    write_UUID_service=bluetoothGattService.getUuid();
                    Log.e(TAG,"write_chara="+write_UUID_chara+"----write_service="+write_UUID_service);

                }
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                    notify_UUID_chara=characteristic.getUuid();
                    notify_UUID_service=bluetoothGattService.getUuid();
                    Log.e(TAG,"notify_chara="+notify_UUID_chara+"----notify_service="+notify_UUID_service);
                }
                if ((charaProp & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0) {
                    indicate_UUID_chara=characteristic.getUuid();
                    indicate_UUID_service=bluetoothGattService.getUuid();
                    Log.e(TAG,"indicate_chara="+indicate_UUID_chara+"----indicate_service="+indicate_UUID_service);

                }
            }
        }
    }
    BluetoothAdapter.LeScanCallback leScanCallback=new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice bluetoothDevice, int i, byte[] bytes) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if(!mDatas.contains(bluetoothDevice)&&bluetoothDevice.getName()!=null){
                        mDatas.add(bluetoothDevice);
                        mRssis.add(i);
                        mAdapter.notifyDataSetChanged();

                    }
                }
            });



        }
    };

    private void checkPermissions(){
        RxPermissions rxPermissions=new RxPermissions(SearchDeviceActivity.this);
        rxPermissions.request(Manifest.permission.ACCESS_FINE_LOCATION)
                .subscribe(new io.reactivex.functions.Consumer<Boolean>(){
                    @Override
                    public void accept(Boolean aBoolean) throws Exception {

                        if (aBoolean) {
                            // 用户已经同意该权限
                            searchBlueTooth();

                        } else {
                            // 用户拒绝了该权限，并且选中『不再询问』
                            Toast toast=Toast.makeText(SearchDeviceActivity.this,"用户开启权限后才能使用",Toast.LENGTH_LONG);
                        }
                    }
                });

    }


}
